
package com.shiku.imserver.repository;


import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.shiku.imserver.common.IService;
import com.shiku.imserver.common.message.ChatMessage;
import com.shiku.imserver.common.utils.Callback;
import com.shiku.imserver.common.utils.ThreadUtil;
import com.shiku.imserver.service.IMBeanUtils;
import com.shiku.utils.StringUtil;

import java.util.HashSet;
import java.util.Set;

import org.bson.Document;
import org.bson.conversions.Bson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class ServiceRepository
        extends BaseRepository
        implements IService {
    private static final String INTERCEPTKEYWORD = "msgIntercept";
    private static Logger logger = LoggerFactory.getLogger(ServiceRepository.class);


    private static final String NEWFRIENDS = "shiku_newFirend";


    private static final String NOTKEYWORD = "keyWord";


    private static final String CONFIG = "config";


    private MongoDatabase newFriendDB;


    private MongoClient mongoClient;


    private MongoClientURI mongoApiUri;


    private Set<String> allKeyWord = new HashSet<>();


    @Override
    public boolean initialize() {

        try {

            getMongoClient();


            getAllKeyWord();

        } catch (Exception ex) {

            ex.printStackTrace();

            return false;

        }


        return true;

    }


    public void saveInterceptKeyWord(String userId, String toUserId, String roomJid, String content) {

        Document dbObj = new Document();

        dbObj.put("sender", Long.valueOf(userId));

        if (StringUtil.isEmpty(userId)) {

            dbObj.put("receiver", Long.valueOf(toUserId));

        }

        if (!StringUtil.isEmpty(roomJid)) {

            dbObj.put("roomJid", roomJid);

        }

        dbObj.put("content", content);

        dbObj.put("createTime", Long.valueOf(System.currentTimeMillis()));


        MongoCollection collection = getCollection("msgIntercept");

        collection.insertOne(dbObj);

    }


    public String filterKeyWord(ChatMessage message) {

        if (StringUtil.isEmpty(message.getContent())) {

            return null;

        }

        boolean match = false;

        String keyWord = null;

        for (String str : this.allKeyWord) {

            if (message.getContent().toLowerCase().contains(str)) {

                keyWord = str;

                match = true;

                break;

            }

        }

        if (match) {

            if (2 == message.getMessageHead().getChatType()) {

                saveInterceptKeyWord(message.getFromUserId(), null, message.getToUserId(), message.getContent());

            } else {


                saveInterceptKeyWord(message.getFromUserId(), message.getToUserId(), null, message.getContent());

            }

        }

        return keyWord;

    }


    public Set<String> getAllKeyWord() {

        MongoCollection<Document> dbCollection = getCollection("keyWord");

        MongoCursor<Document> iterator = dbCollection.find().iterator();

        Document dbObj = null;

        Set<String> keyWords = new HashSet<>();

        while (iterator.hasNext()) {

            dbObj = (Document) iterator.next();

            if (null == dbObj) {
                continue;
            }

            keyWords.add(dbObj.get("word").toString().toLowerCase());

        }

        this.allKeyWord = keyWords;

        return keyWords;

    }


    private MongoCollection getCollection(String dbName) {

        MongoCollection dbCollection = null;

        if (null != this.mongoClient) {

            dbCollection = this.mongoClient.getDatabase(this.mongoApiUri.getDatabase()).getCollection(dbName);

        } else {

            dbCollection = getMongoClient().getDatabase(this.mongoApiUri.getDatabase()).getCollection(dbName);

        }
        return dbCollection;

    }


    private MongoClient getMongoClient() {

        try {

            if (null != this.mongoClient) {

                return this.mongoClient;

            }

            String apiUri = IMBeanUtils.getImconfig().getMongoConfig().getApiUri();

            if (null == apiUri) {
                apiUri = IMBeanUtils.getImconfig().getMongoConfig().getUri();
            }

            System.out.println("mongoClient  is ---null");

            MongoClientOptions.Builder builder = MongoClientOptions.builder();

            builder.socketKeepAlive(true);

            builder.socketTimeout(20000);

            builder.connectTimeout(20000);

            builder.maxWaitTime(12000000);

            builder.heartbeatFrequency(2000);

            this.mongoApiUri = new MongoClientURI(apiUri);


            this.mongoClient = new MongoClient(this.mongoApiUri);

            return this.mongoClient;

        } catch (Exception e) {

            e.printStackTrace();

            return null;

        }

    }


    private void initConfig() {

        Document config = getConfig();

        int xmppTimeout = config.getInteger("XMPPTimeout").intValue();

        if (0 == xmppTimeout) {
            xmppTimeout = 180;
        }

        xmppTimeout *= 1000;

    }


    public boolean getKeyWord(String keyword) {

        MongoCollection<Document> dbCollection = getCollection("keyWord");

        Document query = new Document();

        query.put("word", new Document("$regex", keyword));

        long count = dbCollection.count((Bson) query);

        return (count > 0L);

    }


    public Document getConfig() {

        Document keys = new Document();

        keys.put("XMPPTimeout", Integer.valueOf(1));

        keys.put("isSaveMsg", Integer.valueOf(1));

        keys.put("isSaveMucMsg", Integer.valueOf(1));

        keys.put("isMsgSendTime", Integer.valueOf(1));

        keys.put("isKeyWord", Integer.valueOf(1));

        MongoCollection<Document> dbCollection = getCollection("config");

        Document obj = (Document) dbCollection.find((Bson) new Document()).projection((Bson) keys).first();

        logger.info("getConfig ", obj.toJson());

        return obj;

    }


    public void saveNewFriendsInThread(final long userId, final long toUserId, final Object from, final int direction, final int type, final String content) {

        ThreadUtil.executeInThread(new Callback() {

            @Override
            public void execute(Object obj) {

                ServiceRepository.this.saveNewFriends(userId, toUserId, from, direction, type, content);

            }

        });

    }


    public void saveNewFriends(long userId, long toUserId, Object from, int direction, int type, String content) {

        Document query = new Document("userId", Long.valueOf(userId));

        query.put("toUserId", Long.valueOf(toUserId));


        MongoCollection<Document> collection = getCollection(this.newFriendDB, userId);


        Document dbObj = new Document();


        Document obj = (Document) collection.find((Bson) query).first();


        long modifyTime = System.currentTimeMillis() / 1000L;

        if (null == content) {
            content = "";
        }

        if (500 == type) {
            dbObj.put("from", from);
        }

        if (null == obj) {

            dbObj.put("userId", Long.valueOf(userId));

            dbObj.put("toUserId", Long.valueOf(toUserId));

            dbObj.put("direction", Integer.valueOf(direction));

            dbObj.put("createTime", Long.valueOf(modifyTime));

            dbObj.put("modifyTime", Long.valueOf(modifyTime));

            dbObj.put("type", Integer.valueOf(type));

            dbObj.put("content", content);

            collection.insertOne(dbObj);

        } else {

            dbObj.put("content", content);

            dbObj.put("direction", Integer.valueOf(direction));

            dbObj.put("type", Integer.valueOf(type));

            dbObj.put("content", content);

            dbObj.put("modifyTime", Long.valueOf(modifyTime));

            collection.updateOne((Bson) query, (Bson) new Document("$set", dbObj));

        }

    }

}


